﻿using AlOss;
using com.kmer;
using com.kmer.ApiServer;
using com.kmer.ApiServer.Attributes;
using com.kmer.Attributes;
using com.kmer.db;
using com.kmer.Helper;
using com.kmer.library.Helper;
using EntityFramework.Extensions;
using kmer.Web.Helper;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;

namespace TouchUIWeiXinAPI
{
    /// <summary>
    /// 图片API
    /// </summary>
    public class WXImageHandler : WXBaseHandler
    {
        #region 属性
        readonly Dictionary<string, string> _uploadPaths = new Dictionary<string, string>(){
            { "USER" ,"~/upfile/Avatar" },
            { "WXIMG" ,"OrderApp" }
        };

        private km_platformEntities db_context;

        object returnKindEditor(bool succ, string txt)
        {
            if (succ)
            {
                return new
                {
                    error = 0,
                    url = txt
                };
            }
            return new
            {
                error = 1,
                message = txt
            };
        }
        #endregion

        #region 构造函数
        public WXImageHandler()
        {
            db_context = new km_platformEntities();
        }
        #endregion

        #region API

        /// <summary>
        /// 根据图片ID获取图片地址
        /// </summary>
        /// <param name="ID"></param>
        /// <param name="Mode"></param>
        /// <param name="Style"></param>
        /// <param name="Protocol"></param>
        /// <param name="Type"></param>
        /// <returns></returns>
        //[MustLogin]
        [Description("根据图片ID获取图片地址")]
        public ApiResult Show(
            [Description("图片ID")]
            Guid ID,
            [Description("预制的图片格式（尺寸、缩放方式等等），空表示使用原图 -- 未实现")]
            string Mode = "",
            [Description("代表需要一张宽（w）100px、高（h）100px、绝对质量（Q）90%、jpg格式的图片，空表示使用原图，Mode参数优先！ -- 未实现")]
            string Style = "",
            [Description("协议，空或者无法识别则使用默认设置（一般是http) -- 未实现")]
            string Protocol = "http",
            [Description("返回的数据格式，0-标准格式，1-url字符串。 -- 未实现")]
            int Type = 0)
        {

            var img = db_context.kmImages.FirstOrDefault(i => i.ID == ID);
            if (img == null)
                return Error("图片不存在", 404);
            return Success(ImageHelper.GetImageUrl(Request.ResolveClientUrl(img.Url), Protocol));
        }

        /// <summary>
        /// 删除图片
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        //[MustLogin]
        [Description("删除图片")]
        [ReturnType(typeof(string), "成功返回 OK")]
        public ApiResult Remove([ParamDescription("要删除的图片ID")]Guid id)
        {

            var img = db_context.kmImages.FirstOrDefault(i => i.ID == id);
            if (img == null)
                return Error("图片不存在", 404);
            db_context.kmImages.Where(i => i.ID == img.ID).Delete();
            try
            {
                db_context.SaveChanges();
            }
            catch (Exception ex)
            {
                return Error(ex);
            }
            if (!string.IsNullOrWhiteSpace(img.BucketName))
            {
                var oss = OssHelper.GetClient(img.BucketName);
                oss.DeleteObject(img.Url);
                return Success("OK");
            }
            if (!img.Url.StartsWith("~/") && !img.Url.StartsWith("/"))
                return Success("OK");
            var fileToDel = img.Url.StartsWith("/")
                ? img.Url
                : Server.MapPath(img.Url);
            try
            {
                File.Delete(fileToDel);
            }
            catch (FileNotFoundException ex)
            {
                Log.Error(ex);
            }
            catch (Exception ex)
            {
                return Error(ex);
            }
            return Success("OK");
        }
        /// <summary>
        /// 更新去OSS
        /// </summary>
        /// <param name="basePath"></param>
        /// <returns></returns>
        //[MustLogin]
        [Description("上传到图片到OSS服务器（根据配置）")]
        [ReturnType(typeof(IList<kmImages>))]
        public ApiResult UploadToOss([ParamDescription("保存地址")]string basePath = "",
            [ParamDescription("订货会内码ID")] int? MasterID = null, 
            [ParamDescription("流水号")] string SerialNo = "")
        {
            if (string.IsNullOrWhiteSpace(basePath))
                basePath = Request.Get("basePath", "");
            var vPath = (_uploadPaths[basePath.ToUpper()] + "/" + DateTime.Now.ToString("yyyyMMdd")).Substring(9);
            var BucketName = this.GetConfiguration("image-oss-BucketName", "");
            var oss = OssHelper.GetClient(BucketName);
            var dc = new km_platformEntities();
            var imgList = new List<kmImages>();
            if ((this.Request.Headers.AllKeys.Contains("X_FILENAME") && this.Request.Headers["X_FILENAME"] == "AJAX")
                || this.Request.Get("X_FILENAME", "") == "AJAX")
            {
                var length = Request.ContentLength;
                Request.InputStream.Seek(0, SeekOrigin.Begin);
                var bytes = Request.BinaryRead(length);
                var name = DateTime.Now.Ticks.ToString();
                var toSave = getFileName(vPath, Request.Get("fn", name));
                //var toSave = vPath + name;
                oss.UploadDataAsync(toSave, bytes);
                var img = new kmImages()
                {
                    ID = Guid.NewGuid(),
                    Title = Request.Get("fn", name),
                    Url = toSave,
                    BucketName = BucketName
                };
                if (SaveImg(img))
                {
                    imgList.Add(img);
                }
            }
            else
            {
                for (var i = 0; i < Request.Files.Count; i++)
                {
                    var postFile = Request.Files[i];
                    var name = DateTime.Now.Ticks.ToString();
                    //var toSave = vPath + name;
                    var toSave = getFileName(vPath, postFile);
                    byte[] data = new byte[postFile.InputStream.Length];
                    postFile.InputStream.Read(data, 0, (int)postFile.InputStream.Length);
                    oss.UploadDataAsync(toSave, data);

                    //oss.UploadDataAsync(toSave, postFile.InputStream);
                    var img = new kmImages()
                    {
                        ID = Guid.NewGuid(),
                        Title = postFile.FileName,
                        Url = toSave,
                        BucketName = BucketName
                    };
                    if (SaveImg(img))
                    {
                        imgList.Add(img);
                    }
                }
            }
            foreach (var img in imgList)
            {
                img.Url = oss.GetImageUrl(img.Url);
            }

            switch (imgList.Count)
            {
                case 0:
                    return Error("上传失败");
                case 1:
                    return Success(imgList[0]);
                default:
                    return Success(imgList);
            }
        }
        /// <summary>
        /// 保存去OSS
        /// </summary>
        /// <param name="ImageName"></param>
        /// <param name="BucketName"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        //[MustLogin]
        [Description("保存OSS服务器图片，APP（或者其他客户端）自行上传到OSS服务器，然后使用此API保存相关信息")]
        [ReturnType(typeof(kmImages), "OSS地址请自行拼接")]
        public ApiResult SaveOss([ParamDescription("图片名称，如果空自动使用“key”")]string ImageName,
            [ParamDescription("OSS BucketName")]string BucketName,
            [ParamDescription("key")]string Key)
        {
            if (string.IsNullOrWhiteSpace(BucketName))
            {
                return Error("BucketName 不能为空");
            }
            if (string.IsNullOrWhiteSpace(Key))
            {
                return Error("Key 不能为空");
            }
            if (!OssHelper.BucketExist(BucketName))
            {
                return Error("BucketName 不存在");
            }
            if (!OssHelper.ObjectExist(BucketName, Key))
            {
                return Error("BucketName 不存在");
            }
            var img = new kmImages()
            {
                ID = Guid.NewGuid(),
                Title = string.IsNullOrWhiteSpace(ImageName) ? Key : ImageName,
                Url = Key,
                BucketName = BucketName,
            };
            db_context.kmImages.Add(img);
            try
            {
                db_context.SaveChanges();
            }
            catch (
               Exception ex
               )
            {
                return Error(ex);
            }
            img.Url = getOssUrl(img);
            return Success(img);
        }

        /// <summary>
        /// 待审商品列表图片上传
        /// 作者：曹亚亮
        /// 时间：2018-03-16
        /// </summary>
        /// <param name="photoData">Base64 图片数据</param>
        /// <param name="MasterID">订货会内码ID</param>
        /// <param name="SerialNo">流水号</param>
        /// <param name="GUID">图片GUID</param>
        /// <returns></returns>
        //[MustLogin]
        [Description("上传待审商品列表图片")]
        [ReturnType(typeof(string), "成功返回 GUID")]
        public ApiResult UpPendingGoodsImgToOss([ParamDescription("Base64")] string photoData = "",
            [ParamDescription("订货会内码ID")] int? MasterID = null, [ParamDescription("流水号")] string SerialNo = "",
            [ParamDescription("图片GUID")] string GUID = "", [ParamDescription("OpenId")] string OpenId = "")
        {
            try
            {
                if (string.IsNullOrEmpty(OpenId)) return Error("OpenID不能为空!");
                if (string.IsNullOrWhiteSpace(photoData)) return Error("数据有误");
                if (!MasterID.HasValue) return Error("订货会内码ID不能为空!");
                if (string.IsNullOrWhiteSpace(SerialNo)) return Error("流水号不能为空!");
                if (!GetPermissions(OpenId)) return Error("改用户没有权限操作!");

                #region 图片压缩

                var bytes = Convert.FromBase64String(photoData);
                using (Image usedImg = Image.FromStream(new MemoryStream(bytes)))
                {
                    var newImg = ImageThumbnailHelper.SizeImageWithOldPercent(usedImg, 1, 1);
                    var bytesToOss = Bitmap2Byte(newImg);

                    //图片保存路径;http://kmer-online-pic.oss-cn-shenzhen.aliyuncs.com/OrderApp/{MasterID}/{SerialNo}.jpg 

                    var bucketName = this.GetConfiguration("image-oss-BucketName", "");
                    var toSave = "OrderApp/" + MasterID + "/" + SerialNo + ".jpg";
                    var mTitle = MasterID + "/" + SerialNo;
                    var oss = OssHelper.GetClient(bucketName);
                    IAsyncResult result = oss.UploadDataAsync(toSave, bytesToOss);
                    //IAsyncResult result = oss.UploadDataAsync(toSave, bytes);

                    if (result.IsCompleted)
                    {
                        string imgGuid = string.Empty;
                        var query = db_context.kmImages.FirstOrDefault(o => o.Title == mTitle);
                        if (query == null)
                        {
                            var addGuid = Guid.NewGuid();
                            if (string.IsNullOrWhiteSpace(GUID))
                            {
                                var img = new kmImages()
                                {
                                    ID = addGuid,
                                    Title = mTitle, //保存 订货会ID/流水号 
                                    Url = toSave,
                                    BucketName = bucketName,
                                };

                                if (SaveImg(img))
                                {
                                    imgGuid = addGuid.ToString();
                                }
                                else
                                {
                                    return Error("保存图片GUID失败");
                                }
                            }
                            else
                            {
                                imgGuid = GUID;
                            }
                        }
                        return Success(imgGuid);
                    }
                    else
                    {
                        return Error("上传图片失败");
                    }
                }

                #endregion

            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return Error(ex.Message);
            }
        }


        [Description("上传到图片到OSS服务器（根据配置）")]
        [ReturnType(typeof(IList<kmImages>))]
        public ApiResult WxUploadToOss([ParamDescription("保存地址")] string basePath = "")
        {
            if (string.IsNullOrWhiteSpace(basePath))
                basePath = Request.Get("basePath", "");
            var vPath = _uploadPaths[basePath.ToUpper()];
            //订货会ID
            var masterId = Request.Get("MasterID", "");
            //流水号
            var serialNo = Request.Get("SerialNo", "");
            for (var i = 0; i < Request.Files.Count; i++)
            {
                var postFile = Request.Files[i];
                byte[] data = new byte[postFile.InputStream.Length];
                using (Image usedImg = Image.FromStream(postFile.InputStream))
                {
                    var newImg = ImageThumbnailHelper.SizeImageWithOldPercent(usedImg, 1, 1);
                    var bytesToOss = Bitmap2Byte(newImg);
                    
                    var bucketName = this.GetConfiguration("image-oss-BucketName", "");
                    var toSave = vPath + "/" + masterId + "/" + serialNo + ".jpg";
                    var mTitle = masterId + "/" + serialNo;
                    var oss = OssHelper.GetClient(bucketName);
                    IAsyncResult result = oss.UploadDataAsync(toSave, bytesToOss);
                    if (!result.IsCompleted) return Error("上传图片失败");
                    var imgList = new List<kmImages>();
                        var addGuid = Guid.NewGuid();
                        var img = new kmImages()
                        {
                            ID = addGuid,
                            Title = mTitle, //保存 订货会ID/流水号 
                            Url = toSave,
                            BucketName = bucketName,
                        };

                        if (WxSaveImg(img))
                        {
                            imgList.Add(img);
                        }
                        else
                        {
                            return Error("保存图片GUID失败");
                        }
                        
                    foreach (var g in imgList)
                    {
                        img.Url = oss.GetImageUrl(g.Url);
                    }

                    switch (imgList.Count)
                    {
                        case 0:
                            return Error("上传失败");
                        case 1:
                            return Success(imgList[0]);
                        default:
                            return Success(imgList);
                    }
                }
            }
            return Error("图片对象为空");
        }

        #endregion

        #region  私有方法
        /// <summary>
        /// 获取OSS目录
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        private string getOssUrl(kmImages img)
        {
            if (string.IsNullOrWhiteSpace(img.BucketName))
                return img.Url;
            return OssHelper.GetImageUrl(img.BucketName, img.Url);
        }
        /// <summary>
        /// 删除图片
        /// </summary>
        /// <param name="id"></param>
        /// <param name="dc"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        private bool RemoveImage(Guid id, HttpServerUtility server)
        {
            var img = db_context.kmImages.FirstOrDefault(i => i.ID == id);
            if (img == null)
                return false;
            db_context.kmImages.Where(i => i.ID == img.ID).Delete();
            try
            {
                db_context.SaveChanges();
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return false;
            }
            if (!img.Url.StartsWith("~/") && !img.Url.StartsWith("/")) return true;
            var fileToDel = img.Url.StartsWith("/")
                ? img.Url
                : server.MapPath(img.Url);
            try
            {
                File.Delete(fileToDel);
            }
            catch (FileNotFoundException ex)
            {
                Log.Error(ex);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return false;
            }
            return true;
        }
        private string getFileName(string vPath, string fileName)
        {
            if (fileName.Contains("."))
            {
                var name = DateTime.Now.Ticks.ToString();
                var ss = fileName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                return $"{vPath}/{name}.{ss.LastOrDefault()}";
            }
            return $"{vPath}/{fileName}".Replace("//", "/"); ;
        }
        private string getFileName(string vPath, HttpPostedFile postFile)
        {
            var name = DateTime.Now.Ticks.ToString();
            var ss = postFile.FileName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
            return $"{vPath}/{name}.{ss.LastOrDefault()}".Replace("//", "/");
        }
        private bool SaveImg(kmImages img)
        {
            db_context.kmImages.Add(img);
            try
            {
                db_context.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return false;
            }
        }
        private bool WxSaveImg(kmImages img)
        {
            using (var tran = db_context.Database.BeginTransaction())
            {
                try
                {
                    var query = db_context.kmImages.Where(d => d.Title == img.Title).Select(d => d);
                    db_context.kmImages.RemoveRange(query);
                    db_context.kmImages.Add(img);
                    db_context.SaveChanges();
                    tran.Commit();
                    return true;
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                    Log.Error(ex);
                    return false;
                }
            }
        }
        private static byte[] Bitmap2Byte(Bitmap bitmap)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                bitmap.Save(stream, ImageFormat.Jpeg);
                byte[] data = new byte[stream.Length];
                stream.Seek(0, SeekOrigin.Begin);
                stream.Read(data, 0, Convert.ToInt32(stream.Length));
                return data;
            }
        }

        private bool GetPermissions(string OpenID)
        {
            var user = db_context.t_order_wx_account.FirstOrDefault(
                d => d.OpenId == OpenID && !d.IsDisable && !d.IsRemove && (d.AccountType == 3 || d.AccountType == 0));
            return user != null;
        }
        #endregion
    }
}
